package com.meng.android.util;

import java.util.HashMap;

import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import android.view.View;

public class FormValidation {

	private static final String LOG_CAT = FormValidation.class.getName();

	String errorMessageDefault = "";
	String errorMessageEmpty = "";

	public static final int _NOT_EMPTY = 1;
	public static final int _EMAIL = 2;
	public static final int _SAME_AS = 3;
	public static final int _MIN = 4;
	public static final int _MAX = 5;

	public static final int _FILTER_ALL = 10;
	public static final int _FILTER_FOUND_AND_RETURN = 11;

	private int mStatus = _FILTER_ALL;
	private Context mContext;
	private HashMap<String, Filter> mapFilter = new HashMap<String, Filter>();

	public FormValidation(Context context) {
		this.mContext = context;
		populateMessageResource();
	}

	private void populateMessageResource() {
		Resources res = mContext.getResources();
		this.errorMessageDefault = res
				.getString(R.string.error_message_not_found);
		this.errorMessageEmpty = res.getString(R.string.error_message_empty);
	}

	public void add(String properties, View mView, int filter) {
		if (mapFilter.containsKey(properties)) {
			mapFilter.get(properties).add(filter);
		} else {
			mapFilter.put(properties, new Filter(properties,
					new int[] { filter }, mView));
		}
	}

	public void add(String properties, View mView, int[] filters) {
		if (mapFilter.containsKey(properties)) {
			mapFilter.get(properties).add(filters);
		} else {
			mapFilter.put(properties, new Filter(properties, filters, mView));
		}
	}

	public void add(String properties, int filter) {
		add(properties, null, new int[] { filter });
	}

	public int getStatus() {
		return mStatus;
	}

	public void setStatus(int mStatus) {
		this.mStatus = mStatus;
	}

	public boolean validate(Object obj) {
		boolean result = true;
		for (Filter f : mapFilter.values()) {
			if (!f.validate(obj)) {
				result = false;
				if (mStatus == _FILTER_FOUND_AND_RETURN) {
					return false;
				}
			}
		}
		return result;
	}

	public boolean validate(String field, Object obj) {
		Filter filter = mapFilter.get(field);
		if (filter != null) {
			filter.validate(obj);
		}
		return false;
	}

	/**
	 * Filter class
	 */
	public class Filter {
		String properties;
		View mView;
		int[] filter;

		public Filter(String properties, int[] filter, View mView) {
			this.properties = properties;
			this.filter = filter;
			this.mView = mView;
		}

		public void add(int[] filters) {
			for (int i = 0; i < filters.length; i++) {
				add(filters[i]);
			}
		}

		public void add(int filter) {
			// only work on API 9
			// Arrays.copyOf(filter, filter);
			final int[] newValue = new int[this.filter.length + 1];
			int i = 0;
			for (i = 0; i < this.filter.length; i++) {
				newValue[i] = this.filter[i];
			}
			this.filter[i] = filter;
		}

		/**
		 * validate with value from view, and using filter to validate
		 * 
		 * @return true when valid and false when invalid
		 */
		public boolean validate() {
			Object value = ComponentUtils.getValue(mView);
			Log.i(LOG_CAT, "value: " + value);
			return true;
		}

		/**
		 * @param obj
		 * @return
		 */
		public boolean validate(Object obj) {
			boolean result = true;
			Object value = BeanUtils.getProperty(obj, properties);
			Log.i(LOG_CAT, "value.getClass(): " + value.getClass());
			Log.i(LOG_CAT, "value: " + value);
			for (int i = 0; i < filter.length; i++) {
				switch (filter[i]) {
				case _NOT_EMPTY:
					result = checkNotEmpty(value) ? result : false;
					break;
				default:
					break;
				}
			}
			return result;
		}

		/**
		 * @param obj
		 *            is values will be check, @param obj should be object
		 *            String BigDecimal Double Long etc
		 * @return false when @param obj null or length of trim value equal 0
		 */
		private boolean checkNotEmpty(Object obj) {
			boolean result = true;
			if (obj == null) {
				result = false;
			}
			if (obj instanceof String) {
				result = StringUtils.isNotBlank(String.valueOf(obj));
			}
			if (!result) {
				ComponentUtils.setError(mView,
						String.format(errorMessageEmpty, properties));
			}
			return result;
		}

	}

}